﻿namespace ch06.binary.interpreter
{
    public struct Vm
    {
        internal OperandStack OperandStack;
        internal Module Module;
        internal Memory Memory;

        public Vm(OperandStack op, Module mo) : this()
        {
            OperandStack = op;
            Module = mo;
            InitMem();
        }

        internal void ExecCode(int idx)
        {
            var code = Module.CodeSec[idx];
            foreach (var instr in code.Expr)
            {
                ExecInstr(instr);
            }
        }

        private void InitMem()
        {
            if (Module.MemSec.Length > 0)
            {
                Memory = new Memory(Module.MemSec[0]);
            }

            foreach (var data in Module.DataSec)
            {
                foreach (var instr in data.Offset)
                {
                    ExecInstr(instr);
                }

                Memory.Write(OperandStack.PopU64(), data.Init);
            }
        }

        private void ExecInstr(Instruction instr)
        {
            //fmt.Printf("%s %v\n", instr.GetOpname(), instr.Args)
            var op = Instr.GetInstrFn()[instr.Opcode];
            op(ref this, instr.Args);
        }
    }
}